]> git.saurik.com Git - apple/mdnsresponder.git/blob - mDNSMacOS9/Mac OS Test Responder.c
mDNSResponder-58.3.tar.gz
[apple/mdnsresponder.git] / mDNSMacOS9 / Mac OS Test Responder.c
1 /*
2 * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22
23 Change History (most recent first):
24
25 $Log: Mac\040OS\040Test\040Responder.c,v $
26 Revision 1.17 2003/08/14 02:19:54 cheshire
27 <rdar://problem/3375491> Split generic ResourceRecord type into two separate types: AuthRecord and CacheRecord
28
29 Revision 1.16 2003/08/12 19:56:24 cheshire
30 Update to APSL 2.0
31
32 */
33
34 #include <stdio.h> // For printf()
35 #include <string.h> // For strlen() etc.
36
37 #include <Events.h> // For WaitNextEvent()
38 #include <SIOUX.h> // For SIOUXHandleOneEvent()
39
40 #include "mDNSClientAPI.h" // Defines the interface to the client layer above
41
42 #include "mDNSMacOS9.h" // Defines the specific types needed to run mDNS on this platform
43
44 // These don't have to be globals, but their memory does need to remain valid for as
45 // long as the search is going on. They are declared as globals here for simplicity.
46 static mDNS m;
47 static mDNS_PlatformSupport p;
48 static ServiceRecordSet p1, p2, afp, http, njp;
49 static AuthRecord browsedomain;
50
51 // This sample code just calls mDNS_RenameAndReregisterService to automatically pick a new
52 // unique name for the service. For a device such as a printer, this may be appropriate.
53 // For a device with a user interface, and a screen, and a keyboard, the appropriate
54 // response may be to prompt the user and ask them to choose a new name for the service.
55 mDNSlocal void Callback(mDNS *const m, ServiceRecordSet *const sr, mStatus result)
56 {
57 switch (result)
58 {
59 case mStatus_NoError: debugf("Callback: %##s Name Registered", sr->RR_SRV.resrec.name.c); break;
60 case mStatus_NameConflict: debugf("Callback: %##s Name Conflict", sr->RR_SRV.resrec.name.c); break;
61 case mStatus_MemFree: debugf("Callback: %##s Memory Free", sr->RR_SRV.resrec.name.c); break;
62 default: debugf("Callback: %##s Unknown Result %d", sr->RR_SRV.resrec.name.c, result); break;
63 }
64
65 if (result == mStatus_NameConflict) mDNS_RenameAndReregisterService(m, sr, mDNSNULL);
66 }
67
68 // RegisterService() is a simple wrapper function which takes C string
69 // parameters, converts them to domainname parameters, and calls mDNS_RegisterService()
70 mDNSlocal void RegisterService(mDNS *m, ServiceRecordSet *recordset,
71 UInt16 PortAsNumber, const char txtinfo[],
72 const domainlabel *const n, const char type[], const char domain[])
73 {
74 mDNSIPPort port;
75 domainname t;
76 domainname d;
77 char buffer[512];
78 UInt8 txtbuffer[512];
79
80 port.b[0] = (UInt8)(PortAsNumber >> 8);
81 port.b[1] = (UInt8)(PortAsNumber );
82 MakeDomainNameFromDNSNameString(&t, type);
83 MakeDomainNameFromDNSNameString(&d, domain);
84
85 if (txtinfo)
86 {
87 strncpy((char*)txtbuffer+1, txtinfo, sizeof(txtbuffer)-1);
88 txtbuffer[0] = (UInt8)strlen(txtinfo);
89 }
90 else
91 txtbuffer[0] = 0;
92
93 mDNS_RegisterService(m, recordset,
94 n, &t, &d, // Name, type, domain
95 mDNSNULL, port, // Host and port
96 txtbuffer, (mDNSu16)(1+txtbuffer[0]), // TXT data, length
97 mDNSNULL, 0, // Subtypes (none)
98 mDNSInterface_Any, // Interace ID
99 Callback, mDNSNULL); // Callback and context
100
101 ConvertDomainNameToCString(&recordset->RR_SRV.resrec.name, buffer);
102 printf("Made Service Records for %s\n", buffer);
103 }
104
105 // RegisterFakeServiceForTesting() simulates the effect of services being registered on
106 // dynamically-allocated port numbers. No real service exists on that port -- this is just for testing.
107 mDNSlocal void RegisterFakeServiceForTesting(mDNS *m, ServiceRecordSet *recordset, const char txtinfo[],
108 const char name[], const char type[], const char domain[])
109 {
110 static UInt16 NextPort = 0xF000;
111 domainlabel n;
112 MakeDomainLabelFromLiteralString(&n, name);
113 RegisterService(m, recordset, NextPort++, txtinfo, &n, type, domain);
114 }
115
116 // CreateProxyRegistrationForRealService() checks to see if the given port is currently
117 // in use, and if so, advertises the specified service as present on that port.
118 // This is useful for advertising existing real services (Personal Web Sharing, Personal
119 // File Sharing, etc.) that currently don't register with mDNS Service Discovery themselves.
120 mDNSlocal OSStatus CreateProxyRegistrationForRealService(mDNS *m, UInt16 PortAsNumber, const char txtinfo[],
121 const char *servicetype, ServiceRecordSet *recordset)
122 {
123 mDNSIPPort port;
124 InetAddress ia;
125 TBind bindReq;
126 OSStatus err;
127 TEndpointInfo endpointinfo;
128 EndpointRef ep = OTOpenEndpoint(OTCreateConfiguration(kTCPName), 0, &endpointinfo, &err);
129 if (!ep || err) { printf("OTOpenEndpoint (CreateProxyRegistrationForRealService) failed %d", err); return(err); }
130
131 port.b[0] = (UInt8)(PortAsNumber >> 8);
132 port.b[1] = (UInt8)(PortAsNumber );
133 ia.fAddressType = AF_INET;
134 ia.fPort = port.NotAnInteger;
135 ia.fHost = 0;
136 bindReq.addr.maxlen = sizeof(ia);
137 bindReq.addr.len = sizeof(ia);
138 bindReq.addr.buf = (UInt8*)&ia;
139 bindReq.qlen = 0;
140 err = OTBind(ep, &bindReq, NULL);
141
142 if (err == kOTBadAddressErr)
143 RegisterService(m, recordset, PortAsNumber, txtinfo, &m->nicelabel, servicetype, "local.");
144 else if (err)
145 debugf("OTBind failed %d", err);
146
147 OTCloseProvider(ep);
148 return(noErr);
149 }
150
151 // Done once on startup, and then again every time our address changes
152 mDNSlocal OSStatus mDNSResponderTestSetup(mDNS *m)
153 {
154 char buffer[256];
155 mDNSv4Addr ip = m->HostInterfaces->ip.ip.v4;
156
157 ConvertDomainNameToCString(&m->hostname, buffer);
158 printf("Name %s\n", buffer);
159 printf("IP %d.%d.%d.%d\n", ip.b[0], ip.b[1], ip.b[2], ip.b[3]);
160
161 printf("\n");
162 printf("Registering Service Records\n");
163 // Create example printer discovery records
164 //static ServiceRecordSet p1, p2;
165
166 #define SRSET 0
167 #if SRSET==0
168 RegisterFakeServiceForTesting(m, &p1, "path=/index.html", "Web Server One", "_http._tcp.", "local.");
169 RegisterFakeServiceForTesting(m, &p2, "path=/path.html", "Web Server Two", "_http._tcp.", "local.");
170 #elif SRSET==1
171 RegisterFakeServiceForTesting(m, &p1, "rn=lpq1", "Epson Stylus 900N", "_printer._tcp.", "local.");
172 RegisterFakeServiceForTesting(m, &p2, "rn=lpq2", "HP LaserJet", "_printer._tcp.", "local.");
173 #else
174 RegisterFakeServiceForTesting(m, &p1, "rn=lpq3", "My Printer", "_printer._tcp.", "local.");
175 RegisterFakeServiceForTesting(m, &p2, "lrn=pq4", "My Other Printer", "_printer._tcp.", "local.");
176 #endif
177
178 // If AFP Server is running, register a record for it
179 CreateProxyRegistrationForRealService(m, 548, "", "_afpovertcp._tcp.", &afp);
180
181 // If Web Server is running, register a record for it
182 CreateProxyRegistrationForRealService(m, 80, "", "_http._tcp.", &http);
183
184 // And pretend we always have an NJP server running on port 80 too
185 //RegisterService(m, &njp, 80, "NJP/", &m->nicelabel, "_njp._tcp.", "local.");
186
187 // Advertise that apple.com. is available for browsing
188 mDNS_AdvertiseDomains(m, &browsedomain, mDNS_DomainTypeBrowse, mDNSInterface_Any, "IL 2\\4th Floor.apple.com.");
189
190 return(kOTNoError);
191 }
192
193 // YieldSomeTime() just cooperatively yields some time to other processes running on classic Mac OS
194 mDNSlocal Boolean YieldSomeTime(UInt32 milliseconds)
195 {
196 extern Boolean SIOUXQuitting;
197 EventRecord e;
198 WaitNextEvent(everyEvent, &e, milliseconds / 17, NULL);
199 SIOUXHandleOneEvent(&e);
200 return(SIOUXQuitting);
201 }
202
203 int main()
204 {
205 extern void mDNSPlatformIdle(mDNS *const m); // Only needed for debugging version
206 mStatus err;
207 Boolean DoneSetup = false;
208
209 SIOUXSettings.asktosaveonclose = false;
210 SIOUXSettings.userwindowtitle = "\pMulticast DNS Responder";
211
212 printf("Prototype Multicast DNS Responder\n\n");
213 printf("WARNING! This is experimental software.\n\n");
214 printf("Multicast DNS is currently an experimental protocol.\n\n");
215 printf("This software reports errors using MacsBug breaks,\n");
216 printf("so if you don't have MacsBug installed your Mac may crash.\n\n");
217 printf("******************************************************************************\n");
218
219 err = InitOpenTransport();
220 if (err) { debugf("InitOpenTransport failed %d", err); return(err); }
221
222 err = mDNS_Init(&m, &p, mDNS_Init_NoCache, mDNS_Init_ZeroCacheSize,
223 mDNS_Init_AdvertiseLocalAddresses, mDNS_Init_NoInitCallback, mDNS_Init_NoInitCallbackContext);
224 if (err) return(err);
225
226 while (!YieldSomeTime(35))
227 {
228 // For debugging, use "#define __ONLYSYSTEMTASK__ 1" and call mDNSPlatformIdle() periodically.
229 // For shipping code, don't define __ONLYSYSTEMTASK__, and you don't need to call mDNSPlatformIdle()
230 mDNSPlatformIdle(&m); // Only needed for debugging version
231 if (m.mDNSPlatformStatus == mStatus_NoError && !DoneSetup)
232 {
233 DoneSetup = true;
234 printf("\nListening for mDNS queries...\n");
235 mDNSResponderTestSetup(&m);
236 }
237 }
238
239 if (p1.RR_SRV.resrec.RecordType ) mDNS_DeregisterService(&m, &p1);
240 if (p2.RR_SRV.resrec.RecordType ) mDNS_DeregisterService(&m, &p2);
241 if (afp.RR_SRV.resrec.RecordType ) mDNS_DeregisterService(&m, &afp);
242 if (http.RR_SRV.resrec.RecordType) mDNS_DeregisterService(&m, &http);
243 if (njp.RR_SRV.resrec.RecordType ) mDNS_DeregisterService(&m, &njp);
244
245 mDNS_Close(&m);
246
247 return(0);
248 }